#ifndef __BLOCK_QUEUE_HPP__
#define __BLOCK_QUEUE_HPP__

#include<iostream>
#include<pthread.h>
#include<queue>
#include<unistd.h>
#include "Task.hpp"
using namespace std;

// 阻塞队列默认的容量
#define NUM 5

template<class T>
class BlockQueue
{
private:
    bool IsFUll()
    {
        return _q.size() == _cap;
    }
    bool IsEmpty()
    {
        return _q.empty();
    }
public:
    BlockQueue(int cap = NUM) :_cap(cap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_product, nullptr);
        pthread_cond_init(&_comsume, nullptr);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_product);
        pthread_cond_destroy(&_comsume);
    }

    // 生产数据
    void Push(const T& data)
    {
        pthread_mutex_lock(&_mutex);
        // 判断容器是否满了
        while(IsFUll())
        {
            pthread_cond_wait(&_product, &_mutex);
        }
        _q.push(data);
        pthread_mutex_unlock(&_mutex);
        // 唤醒消费线程
        pthread_cond_signal(&_comsume);
    }   

    // 消费数据
    void Pop()
    {
        pthread_mutex_lock(&_mutex);
        // 判断容器是否有数据
        while(IsEmpty())
        {
            pthread_cond_wait(&_comsume,&_mutex);
        }
        // 开始消费数据
        Task t = _q.front();
        cout << "处理了一个任务: ";
        t.Run();
        _q.pop();

        pthread_mutex_unlock(&_mutex);
        // 唤醒生产线程
        pthread_cond_signal(&_product);
    }

private:
    queue<T> _q; // 阻塞队列
    int _cap; // 阻塞队列的最大容量
    pthread_mutex_t _mutex; // 互斥锁
    pthread_cond_t _product; // 专门给生产者提供的条件变量
    pthread_cond_t _comsume; // 专门给消费者提供的条件变量
};

#endif